/*
* PureComponent 是用于做性能提示，可以监视state的变化情况，如果更改了才进行更新；否则页面不更新 render
* 当我们的组件继承 PureComponent 后，则开发者不需要自己使用 shouldComponentUpdate 生命周期函数进行判断。
*
* Pure单词有纯净的意思
*
*
* */
import {Component, PureComponent} from 'react';

import PropTypes from 'prop-types'

import './news.css';
import fj from '../../assets/imgs/fj.png';
import Item from '../Item';
import {getNews} from "../../api/news";


class News extends PureComponent {

    constructor(props) {
        super(props);
        this.state = {
            title: 'hi react!',
            flag: true, // 用于控制 Item组件的显示与否
            newsList: [],
            page: 1,
            size: 2,
            total: 0,
            /*
            1. 当前页码
            2. 总记录数
            3. 每页显示的数量

            * */

        }
    }

    static defaultProps = {
        number1: 1000,
    }


    static propTypes = {
        /*
        * Warning: Failed prop type: Invalid prop `number1` of type `string` supplied to `News`, expected `number`.
        * */
        number1: PropTypes.number,
    }

    /**
     * 组件即将挂载到页面dom上，实际还没有（虚拟dom没有转换为真实的dom）
     * 未来有可能废弃，所有这个里面不要写业务
     */
    UNSAFE_componentWillMount() {

        console.log('1. componentWillMount');

    }

    /* shouldComponentUpdate 生命周期决定是否进行组件的更新 如果返回是true则更新；返回false不更新 其主要的原因是为了 性能提升。如果在实际操作代码的时候，如果更新的state和之前的state一样的话，其实是没必要重新渲染页面的 */

    /*shouldComponentUpdate(nextProps, nextState, nextContext) {

        console.log(nextState, '最新的数据');
        console.log(this.state, '修改之前的数据');
        if(nextState.title == this.state.title){
            // 更新的数据是否和之前的旧数据一致；如果一致，则没必要重新渲染数据。
            return false;
        }else{
            return true;
        }

    }*/

    /*更新相关的 1. 属性更新（组件通信 父--->子） 2. 自己的state变化*/
    UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) {

        /*组件的数据即将更新的时候触发*/
        /* nextState 代表新的数据 */
        console.log('4. componentWillUpdate', nextState);

    }

    /*5. render 代表更新的渲染；render 既在产生的时候执行，也在更新的时候执行 */

    /*组件已经更新完毕 prevState代表更新前的数据*/
    componentDidUpdate(prevProps, prevState, snapshot) {

        console.log('5. componentDidUpdate', prevState);
    }


    clickHandler() {
        console.log('clickHandler', this);
        this.setState({
            title: '我是新的标题！',

            flag: !this.state.flag
        })
    }

    /*组件渲染成真实的dom后，执行，这个时候虚拟dom变成了真实的dom到页面上了*/
    componentDidMount() {
        console.log('3. componentDidMount');
        /*一般这个生命周期函数里面进行接口调用，发送网络请求。一般和后台进行交互*/
        /*接口*/
        /*  参照网站 ：http://jy.52kfw.cn/#/home */
        /* let url = 'https://yw.52kfw.cn/api/news/flist?pageSize=5&currentPage=1&cate_id=%E7%A7%91%E6%8A%80%E5%85%B4%E5%9B%BD';*/

        /* 在做项目的时候，一般我们的接口也会进行分目录的管理 */
        this.getNewsList();


    }

    getNewsList = async (page = 1) => {
        let info = await getNews(page); // promise对象
        console.log(info.data, '每页的数据信息');
        let {statusCode} = info.data;
        if (statusCode == 200) {
            let newsList = info.data.data.list;
            let total = info.data.data.total;

            console.log(newsList);

            this.setState({
                newsList: [...this.state.newsList, ...newsList],
                total,
            })

        } else {
            alert('系统繁忙，接口请求失败！');
        }
    }

    loadMore = () => {
        /* 每点击一下，就相当于做了一个翻页操作，代表获取下一页的数据 */
        this.setState({
            page: this.state.page + 1,
        }, () => {

            console.log(this.state.page, '当前请求的页码');
            // 调用接口获取当前页的数据 现在调用分页后，默认的行为是覆盖的显示；如果我们是希望进行追加显示，则我们需要修改一下数据的处理操作。
            // 如果后台的接口没有数据返回了，则我们不需要在进行请求。
            if (this.state.newsList.length >= this.state.total) {
                console.log('数据已经没有了', this.state.page);
                alert('暂无更多的数据信息');

                return;
            }
            this.getNewsList(this.state.page);

        })
        console.log('loadMore');

    }

    /*挂载*/
    render() {
        console.log('2. render');
        // console.log(this.props);// 代表调用方传递的属性数据
        /*Cannot assign to read only property 'number1' of object '#<Object>'*/
        // this.props.number1 = 100; // 错误写法 外部传递的属性是可读。

        let {number1, number2, children} = this.props;
        return (
            <div style={{color: '#f00'}}>
                {/*当 flag为 true的时候，组件显示；当为 false 隐藏，相当于销毁*/}
                {this.state.flag ? <Item/> : <div>Item隐藏了</div>}
                <hr/>
                <h2>新闻列表</h2>
                {
                    this.state.newsList.map(item => {
                        return (
                            <ul key={item._id}>
                                <li>序号：{item._id}</li>
                                <li>标题名称：{item.title}</li>
                                <li>浏览次数：{item.viewCount}</li>
                                <li>作者：{item.author}</li>
                                <li>封面图：<img width={100} src={'https://yw.52kfw.cn' + item.imageUrl} alt=""/></li>
                            </ul>
                        )
                    })
                }
                <hr/>
                <button onClick={this.loadMore}>点击加载更多....</button>
                <hr/>


                <h2>自己的类组件-{this.state.title}-{number1}-{number2}-{children}</h2>
                <img src={fj} width={100} height={100} alt=""/>
                <p>
                    1. 结构
                </p>
                <p>
                    2. 样式
                </p>
                <p>
                    3. 行为 事件
                </p>
                <p>
                    4. 数据（a. 自己维护 state b. props）
                </p>
                <p>
                    5. 生命周期函数（a. 组件产生 b. 组件的更新 c. 组件销毁）
                </p>

                <button onClick={this.clickHandler.bind(this)}>点击提示信息</button>
            </div>
        );
    }

}

export default News;
